<!DOCTYPE html>
<html lang="zh-CN">





<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/myblog/img/apple-touch-icon.png">
  <link rel="icon" type="image/png" href="/myblog/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="TakCode Blog">
  <meta name="author" content="谢芃">
  <meta name="keywords" content="">
  <title>ui组件封装笔记 - TakCode</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/5.12.1/css/all.min.css" />
<link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />
<link  rel="stylesheet" href="https://cdn.staticfile.org/mdbootstrap/4.13.0/css/mdb.min.css" />
<link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/3.0.1/github-markdown.min.css" />

<link rel="stylesheet" href="//at.alicdn.com/t/font_1067060_qzomjdt8bmp.css">



  <link  rel="stylesheet" href="/myblog/lib/prettify/tomorrow-night-eighties.min.css" />

<link  rel="stylesheet" href="/myblog/css/main.css" />


  <link defer rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />


<!-- 自定义样式保持在最底部 -->


<meta name="generator" content="Hexo 4.2.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/myblog/">&nbsp;<strong>TakCode</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/myblog/">首页</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/myblog/archives/">归档</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/myblog/categories/">分类</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/myblog/tags/">标签</a>
          </li>
        
          
          
          
          
          <li class="nav-item">
            <a class="nav-link" href="/myblog/about/">关于</a>
          </li>
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="view intro-2" id="background" parallax=true
         style="background: url('/myblog/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask rgba-black-light flex-center">
          <div class="container text-center white-text fadeInUp">
            <span class="h2" id="subtitle">
              
            </span>

            
              
                <p class="mt-3 post-meta">
                  <i class="fas fa-calendar-alt" aria-hidden="true"></i>
                  星期二, 五月 12日 2020, 8:09 晚上
                </p>
              

              <p class="mt-1">
                
                  
                  <span class="post-meta">
                    <i class="far fa-chart-bar"></i>
                    5.1k 字
                  </span>
                

                
                  
                  <span class="post-meta">
                      <i class="far fa-clock"></i>
                      27 分钟
                  </span>
                

                
              </p>
            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5 z-depth-3" id="board">
          <div class="post-content mx-auto" id="post">
            
            <div class="markdown-body">
              <p>ui组件封装笔记</p>
<a id="more"></a>

<h1 id="常见组件封装"><a href="#常见组件封装" class="headerlink" title="常见组件封装"></a>常见组件封装</h1><h2 id="项目初始化"><a href="#项目初始化" class="headerlink" title="项目初始化"></a>项目初始化</h2><p>使用vue-cli脚手架快速搭建一个vue项目</p>
<pre><code class="js">// 选择scss babel 和 eslint
vue create songyong-ui</code></pre>
<p>启动项目</p>
<pre><code class="js">cd songyong-ui
yarn serve</code></pre>
<h2 id="button组件"><a href="#button组件" class="headerlink" title="button组件"></a>button组件</h2><h3 id="前置知识"><a href="#前置知识" class="headerlink" title="前置知识"></a>前置知识</h3><pre><code class="js">组件通讯
组件插槽
props校验</code></pre>
<h3 id="参数支持"><a href="#参数支持" class="headerlink" title="参数支持"></a>参数支持</h3><table>
<thead>
<tr>
<th>参数名</th>
<th>参数描述</th>
<th>参数类型</th>
<th>默认值</th>
</tr>
</thead>
<tbody><tr>
<td>type</td>
<td>按钮类型(primary / success / warning / danger / info)</td>
<td>string</td>
<td>default</td>
</tr>
<tr>
<td>plain</td>
<td>是否是朴素按钮</td>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>round</td>
<td>是否是圆角按钮</td>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>circle</td>
<td>是否是圆形按钮</td>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>disabled</td>
<td>是否禁用按钮</td>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>icon</td>
<td>图标类名</td>
<td>string</td>
<td>无</td>
</tr>
</tbody></table>
<h3 id="事件支持"><a href="#事件支持" class="headerlink" title="事件支持"></a>事件支持</h3><table>
<thead>
<tr>
<th>事件名</th>
<th>事件描述</th>
</tr>
</thead>
<tbody><tr>
<td>click</td>
<td>点击事件</td>
</tr>
</tbody></table>
<h3 id="基本结构"><a href="#基本结构" class="headerlink" title="基本结构"></a>基本结构</h3><pre><code class="html">&lt;template&gt;
  &lt;button class=&quot;sy-button&quot;&gt;
    &lt;span&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/span&gt;
  &lt;/button&gt;
&lt;/template&gt;</code></pre>
<p>样式</p>
<pre><code class="scss">.sy-button {
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #fff;
  border: 1px solid #dcdfe6;
  color: #606266;
  -webkit-appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: none;
  margin: 0;
  transition: 0.1s;
  font-weight: 500;
  // 禁止元素的文字被选中
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;
  &amp;:hover,
  &amp;:focus {
    color: #409eff;
    border-color: #c6e2ff;
    background-color: #ecf5ff;
  }
}</code></pre>
<h3 id="type属性"><a href="#type属性" class="headerlink" title="type属性"></a>type属性</h3><p>结构</p>
<pre><code class="html">&lt;button class=&quot;sy-button&quot; :class=&quot;[`sy-button--${type}`]&quot;&gt;</code></pre>
<p>js</p>
<pre><code class="js">props: {
  type: {
    type: String,
    default: &#39;default&#39;
  }
},</code></pre>
<p>样式</p>
<pre><code class="scss">.sy-button--primary {
  color: #fff;
  background-color: #409eff;
  border-color: #409eff;

  &amp;:hover,
  &amp;:focus {
    background: #66b1ff;
    border-color: #66b1ff;
    color: #fff;
  }
}
.sy-button--success {
  color: #fff;
  background-color: #67c23a;
  border-color: #67c23a;
  &amp;:hover,
  &amp;:focus {
    background: #85ce61;
    border-color: #85ce61;
    color: #fff;
  }
}
.sy-button--info {
  color: #fff;
  background-color: #909399;
  border-color: #909399;
  &amp;:hover,
  &amp;:focus {
    background: #a6a9ad;
    border-color: #a6a9ad;
    color: #fff;
  }
}
.sy-button--warning {
  color: #fff;
  background-color: #e6a23c;
  border-color: #e6a23c;
  &amp;:hover,
  &amp;:focus {
    background: #ebb563;
    border-color: #ebb563;
    color: #fff;
  }
}
.sy-button--danger {
  color: #fff;
  background-color: #f56c6c;
  border-color: #f56c6c;
  &amp;:hover,
  &amp;:focus {
    background: #f78989;
    border-color: #f78989;
    color: #fff;
  }
}</code></pre>
<h3 id="plain属性"><a href="#plain属性" class="headerlink" title="plain属性"></a>plain属性</h3><pre><code class="scss">// 朴素的按钮
.sy-button.is-plain {
  &amp;:hover,
  &amp;:focus {
    background: #fff;
    border-color: #409eff;
    color: #409eff;
  }
}
.sy-button--primary.is-plain {
  color: #409eff;
  background: #ecf5ff;
  border-color: #b3d8ff;
  &amp;:hover,
  &amp;:focus {
    background: #409eff;
    border-color: #409eff;
    color: #fff;
  }
}
.sy-button--success.is-plain {
  color: #67c23a;
  background: #f0f9eb;
  border-color: #c2e7b0;
  &amp;:hover,
  &amp;:focus {
    background: #67c23a;
    border-color: #67c23a;
    color: #fff;
  }
}

.sy-button--info.is-plain {
  color: #909399;
  background: #f4f4f5;
  border-color: #d3d4d6;
  &amp;:hover,
  &amp;:focus {
    background: #909399;
    border-color: #909399;
    color: #fff;
  }
}
.sy-button--warning.is-plain {
  color: #e6a23c;
  background: #fdf6ec;
  border-color: #f5dab1;
  &amp;:hover,
  &amp;:focus {
    background: #e6a23c;
    border-color: #e6a23c;
    color: #fff;
  }
}
.sy-button--danger.is-plain {
  color: #f56c6c;
  background: #fef0f0;
  border-color: #fbc4c4;
  &amp;:hover,
  &amp;:focus {
    background: #f56c6c;
    border-color: #f56c6c;
    color: #fff;
  }
}</code></pre>
<h3 id="round属性"><a href="#round属性" class="headerlink" title="round属性"></a>round属性</h3><pre><code class="scss">.sy-button.is-round {
  border-radius: 20px;
  padding: 12px 23px;
}</code></pre>
<h3 id="circle属性"><a href="#circle属性" class="headerlink" title="circle属性"></a>circle属性</h3><pre><code class="scss">// 原形按钮
.sy-button.is-circle {
  border-radius: 50%;
  padding: 12px;
}</code></pre>
<h3 id="icon的支持"><a href="#icon的支持" class="headerlink" title="icon的支持"></a>icon的支持</h3><p>在main.js中引入字体图标文件</p>
<pre><code class="js">import &#39;./assets/fonts/font.scss&#39;</code></pre>
<p>结构</p>
<pre><code class="html">&lt;i :class=&quot;icon&quot; v-if=&quot;icon&quot;&gt;&lt;/i&gt;
&lt;slot&gt;&lt;/slot&gt;</code></pre>
<p>js</p>
<pre><code class="js">icon: {
  type: String,
  default: &#39;&#39;
}</code></pre>
<p>样式</p>
<pre><code class="scss">// 按钮后的文本
.sy-button [class*=sy-icon-]+span {
    margin-left: 5px;
}</code></pre>
<h3 id="禁用按钮"><a href="#禁用按钮" class="headerlink" title="禁用按钮"></a>禁用按钮</h3><ul>
<li>props</li>
</ul>
<pre><code class="js">disabled: Boolean</code></pre>
<ul>
<li>结构</li>
</ul>
<pre><code class="js">  &lt;button class=&quot;sy-button&quot; :class=&quot;[`sy-button--${type}`, {
    &#39;is-plain&#39;: plain,
    &#39;is-round&#39;: round,
    &#39;is-circle&#39;: circle,
    &#39;is-disabled&#39;: disabled
    }]&quot;
    :disabled=&quot;disabled&quot;
    @click=&quot;handleClick&quot;
  &gt;</code></pre>
<ul>
<li>样式</li>
</ul>
<pre><code class="scss">// 禁用
.sy-button.is-disabled,
.sy-button.is-disabled:focus,
.sy-button.is-disabled:hover {
    color: #c0c4cc;
    cursor: not-allowed;
    background-image: none;
    background-color: #fff;
    border-color: #ebeef5;
}
.sy-button.is-disabled,
.sy-button.is-disabled:focus,
.sy-button.is-disabled:hover {
    color: #c0c4cc;
    cursor: not-allowed;
    background-image: none;
    background-color: #fff;
    border-color: #ebeef5;
}
.sy-button--primary.is-disabled,
.sy-button--primary.is-disabled:active,
.sy-button--primary.is-disabled:focus,
.sy-button--primary.is-disabled:hover {
    color: #fff;
    background-color: #a0cfff;
    border-color: #a0cfff;
}
.sy-button--success.is-disabled,
.sy-button--success.is-disabled:active,
.sy-button--success.is-disabled:focus,
.sy-button--success.is-disabled:hover {
    color: #fff;
    background-color: #b3e19d;
    border-color: #b3e19d;
}
.sy-button--info.is-disabled,
.sy-button--info.is-disabled:active,
.sy-button--info.is-disabled:focus,
.sy-button--info.is-disabled:hover {
    color: #fff;
    background-color: #c8c9cc;
    border-color: #c8c9cc;
}
.sy-button--warning.is-disabled,
.sy-button--warning.is-disabled:active,
.sy-button--warning.is-disabled:focus,
.sy-button--warning.is-disabled:hover {
    color: #fff;
    background-color: #f3d19e;
    border-color: #f3d19e;
}
.sy-button--danger.is-disabled,
.sy-button--danger.is-disabled:active,
.sy-button--danger.is-disabled:focus,
.sy-button--danger.is-disabled:hover {
    color: #fff;
    background-color: #fab6b6;
    border-color: #fab6b6;
}</code></pre>
<h3 id="click事件支持"><a href="#click事件支持" class="headerlink" title="click事件支持"></a>click事件支持</h3><p>结构</p>
<pre><code class="html">@click=&quot;handleClick&quot;</code></pre>
<p>js</p>
<pre><code class="js">methods: {
  handleClick (e) {
    this.$emit(&#39;click&#39;, e)
  }
}</code></pre>
<h2 id="dialog组件"><a href="#dialog组件" class="headerlink" title="dialog组件"></a>dialog组件</h2><h3 id="前置知识-1"><a href="#前置知识-1" class="headerlink" title="前置知识"></a>前置知识</h3><pre><code class="js">vue过渡与动画
sync修饰符
具名插槽与v-slot指令</code></pre>
<h3 id="参数支持-1"><a href="#参数支持-1" class="headerlink" title="参数支持"></a>参数支持</h3><table>
<thead>
<tr>
<th>参数名</th>
<th>参数描述</th>
<th>参数类型</th>
<th>默认值</th>
</tr>
</thead>
<tbody><tr>
<td>title</td>
<td>对话框标题</td>
<td>string</td>
<td>提示</td>
</tr>
<tr>
<td>width</td>
<td>宽度</td>
<td>string</td>
<td>50%</td>
</tr>
<tr>
<td>top</td>
<td>与顶部的距离</td>
<td>string</td>
<td>15vh</td>
</tr>
<tr>
<td>visible</td>
<td>是否显示dialog（支持sync修饰符）</td>
<td>boolean</td>
<td>false</td>
</tr>
</tbody></table>
<h3 id="事件支持-1"><a href="#事件支持-1" class="headerlink" title="事件支持"></a>事件支持</h3><table>
<thead>
<tr>
<th>事件名</th>
<th>事件描述</th>
</tr>
</thead>
<tbody><tr>
<td>opened</td>
<td>模态框显示的事件</td>
</tr>
<tr>
<td>closed</td>
<td>模态框关闭的事件</td>
</tr>
</tbody></table>
<h3 id="插槽说明"><a href="#插槽说明" class="headerlink" title="插槽说明"></a>插槽说明</h3><table>
<thead>
<tr>
<th>插槽名称</th>
<th>插槽描述</th>
</tr>
</thead>
<tbody><tr>
<td>default</td>
<td>dialog的内容</td>
</tr>
<tr>
<td>title</td>
<td>dialog的标题</td>
</tr>
<tr>
<td>footer</td>
<td>dialog的底部操作区</td>
</tr>
</tbody></table>
<h3 id="基本结构-1"><a href="#基本结构-1" class="headerlink" title="基本结构"></a>基本结构</h3><p>结构</p>
<pre><code class="html">&lt;template&gt;
  &lt;div class=&quot;sy-dialog__wrapper&quot;&gt;
    &lt;div class=&quot;sy-dialog&quot;&gt;
      &lt;div class=&quot;sy-dialog__header&quot;&gt;
        &lt;span class=&quot;sy-dialog__title&quot;&gt;提示&lt;/span&gt;
        &lt;button class=&quot;sy-dialog__headerbtn&quot;&gt;
          &lt;i class=&quot;sy-icon-close&quot;&gt;&lt;/i&gt;
        &lt;/button&gt;
      &lt;/div&gt;
      &lt;div class=&quot;sy-dialog__body&quot;&gt;
        &lt;span&gt;这是一段信息&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;sy-dialog__footer&quot;&gt;
        &lt;sy-button&gt;取消&lt;/sy-button&gt;
        &lt;sy-button type=&quot;primary&quot;&gt;确定&lt;/sy-button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/template&gt;</code></pre>
<p>样式</p>
<pre><code class="scss">.sy-dialog__wrapper {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow: auto;
  margin: 0;
  z-index: 2001;
  background-color: rgba(0,0,0, .5);

  .sy-dialog {
    position: relative;
    margin: 15vh auto 50px;
    background: #fff;
    border-radius: 2px;
    box-shadow: 0 1px 3px rgba(0,0,0,.3);
    box-sizing: border-box;
    width: 30%;

    &amp;__header {
      padding: 20px 20px 10px;
      .sy-dialog__title {
        line-height: 24px;
        font-size: 18px;
        color: #303133;
      }
      .sy-dialog__headerbtn {
        position: absolute;
        top: 20px;
        right: 20px;
        padding: 0;
        background: transparent;
        border: none;
        outline: none;
        cursor: pointer;
        font-size: 16px;
        .el-icon-close {
          color: #909399;
        }
      }
    }

    &amp;__body {
      padding: 30px 20px;
      color: #606266;
      font-size: 14px;
      word-break: break-all;
    }
    &amp;__footer {
      padding: 10px 20px 20px;
      text-align: right;
      box-sizing: border-box;
      .sy-button:first-child {
        margin-right: 20px;
      }
    }
  }
}</code></pre>
<h3 id="title属性"><a href="#title属性" class="headerlink" title="title属性"></a>title属性</h3><blockquote>
<p>title属性既支持传入title属性，也只是传入title插槽</p>
</blockquote>
<p>结构</p>
<pre><code class="html">&lt;slot name=&quot;title&quot;&gt;
  &lt;span class=&quot;sy-dialog__title&quot;&gt;{{title}}&lt;/span&gt;
&lt;/slot&gt;</code></pre>
<p>js</p>
<pre><code class="js">props: {
  title: {
    type: String,
    default: &#39;提示&#39;
  }
}</code></pre>
<h3 id="width属性与top属性"><a href="#width属性与top属性" class="headerlink" title="width属性与top属性"></a>width属性与top属性</h3><p>结构</p>
<pre><code class="html">&lt;div class=&quot;sy-dialog&quot; :style=&quot;style&quot;&gt;</code></pre>
<p>js</p>
<pre><code class="js">  props: {
    title: {
      type: String,
      default: &#39;提示&#39;
    },
    width: {
      type: String,
      default: &#39;50%&#39;
    },
    top: {
      tpye: String,
      default: &#39;15vh&#39;
    }
  },
  computed: {
    style () {
      return {
        width: this.width,
        marginTop: this.top
      }
    }
  }</code></pre>
<h3 id="内容插槽"><a href="#内容插槽" class="headerlink" title="内容插槽"></a>内容插槽</h3><pre><code class="html">&lt;div class=&quot;sy-dialog__body&quot;&gt;
  &lt;!-- 默认插槽 --&gt;
  &lt;slot&gt;&lt;/slot&gt;
&lt;/div&gt;</code></pre>
<h3 id="底部插槽"><a href="#底部插槽" class="headerlink" title="底部插槽"></a>底部插槽</h3><pre><code class="html">&lt;div class=&quot;sy-dialog__footer&quot; v-if=&quot;$slots.footer&quot;&gt;
  &lt;slot name=&quot;footer&quot;&gt;&lt;/slot&gt;
&lt;/div&gt;</code></pre>
<h3 id="控制显示与隐藏"><a href="#控制显示与隐藏" class="headerlink" title="控制显示与隐藏"></a>控制显示与隐藏</h3><p>结构</p>
<pre><code class="html">&lt;div class=&quot;sy-dialog__wrapper&quot; v-show=&quot;visible&quot;&gt;</code></pre>
<p>点击遮罩层关闭</p>
<pre><code class="html">&lt;div class=&quot;sy-dialog__wrapper&quot; v-show=&quot;visible&quot; @click.self=&quot;handleClose&quot;&gt;</code></pre>
<p>点击关闭按钮关闭</p>
<pre><code class="html"> &lt;button class=&quot;sy-dialog__headerbtn&quot; @click=&quot;handleClose&quot;&gt;</code></pre>
<p>关闭处理</p>
<pre><code class="js">handleClose () {
    this.$emit(&#39;update:visible&#39;, false)
}</code></pre>
<h3 id="动画处理"><a href="#动画处理" class="headerlink" title="动画处理"></a>动画处理</h3><p>结构</p>
<pre><code class="html">&lt;transition name=&quot;dialog-fade&quot; @after-enter=&quot;afterEnter&quot; @after-leave=&quot;afterLeave&quot;&gt;&lt;/transition&gt;</code></pre>
<p>样式</p>
<pre><code class="scss">.dialog-fade-enter-active {
  animation: dialog-fade-in .4s;
}

.dialog-fade-leave-active {
  animation: dialog-fade-out .4s;
}

@keyframes dialog-fade-in {
  0% {
    transform: translate3d(0, -20px, 0);
    opacity: 0;
  }
  100% {
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}

@keyframes dialog-fade-out {
  0% {
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
  100% {
    transform: translate3d(0, -20px, 0);
    opacity: 0;
  }
}</code></pre>
<p>js</p>
<pre><code class="js">afterEnter () {
  this.$emit(&#39;opened&#39;)
},
afterLeave () {
  this.$emit(&#39;closed&#39;)
}</code></pre>
<h2 id="input组件"><a href="#input组件" class="headerlink" title="input组件"></a>input组件</h2><h3 id="参数支持-2"><a href="#参数支持-2" class="headerlink" title="参数支持"></a>参数支持</h3><table>
<thead>
<tr>
<th>参数名称</th>
<th>参数描述</th>
<th>参数类型</th>
<th>默认值</th>
</tr>
</thead>
<tbody><tr>
<td>placeholder</td>
<td>占位符</td>
<td>string</td>
<td>无</td>
</tr>
<tr>
<td>type</td>
<td>文本框类型(text/password)</td>
<td>string</td>
<td>text</td>
</tr>
<tr>
<td>disabled</td>
<td>禁用</td>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>clearable</td>
<td>是否显示清空按钮</td>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>show-password</td>
<td>是否显示密码切换按钮</td>
<td>boolean</td>
<td>false</td>
</tr>
<tr>
<td>name</td>
<td>name属性</td>
<td>string</td>
<td>无</td>
</tr>
</tbody></table>
<h3 id="事件支持-2"><a href="#事件支持-2" class="headerlink" title="事件支持"></a>事件支持</h3><table>
<thead>
<tr>
<th>事件名称</th>
<th>事件描述</th>
</tr>
</thead>
<tbody><tr>
<td>blur</td>
<td>失去焦点事件</td>
</tr>
<tr>
<td>change</td>
<td>内容改变事件</td>
</tr>
<tr>
<td>focus</td>
<td>获取的焦点事件</td>
</tr>
</tbody></table>
<h3 id="基本结构-2"><a href="#基本结构-2" class="headerlink" title="基本结构"></a>基本结构</h3><p>节本结构</p>
<pre><code class="html">&lt;template&gt;
  &lt;div class=&quot;sy-input&quot;&gt;
    &lt;input type=&quot;text&quot; class=&quot;sy-input__inner&quot;&gt;
  &lt;/div&gt;
&lt;/template&gt;</code></pre>
<p>样式</p>
<pre><code class="scss">.sy-input {
  width: 100%;
  position: relative;
  font-size: 14px;
  display: inline-block;
  .sy-input__inner {
    -webkit-appearance: none;
    background-color: #fff;
    background-image: none;
    border-radius: 4px;
    border: 1px solid #dcdfe6;
    box-sizing: border-box;
    color: #606266;
    display: inline-block;
    font-size: inherit;
    height: 40px;
    line-height: 40px;
    outline: none;
    padding: 0 15px;
    transition: border-color .2s cubic-bezier(.645,.045,.355,1);
    width: 100%;

    &amp;:focus {
      outline: none;
      border-color: #409eff;
    }
  }
}</code></pre>
<h3 id="props处理placeholde-type-name"><a href="#props处理placeholde-type-name" class="headerlink" title="props处理placeholde, type,name"></a>props处理placeholde, type,name</h3><ul>
<li>placeholer</li>
</ul>
<pre><code class="html">&lt;input type=&quot;text&quot; class=&quot;sy-input__inner&quot; :placeholder=&quot;placeholder&quot;&gt;</code></pre>
<pre><code class="js">  props: {
    placeholder: {
      type: String,
      default: &#39;&#39;
    }
  }</code></pre>
<ul>
<li>type属性-密码框</li>
</ul>
<pre><code class="html">    &lt;input
      class=&quot;sy-input__inner&quot;
      :placeholder=&quot;placeholder&quot;
      :type=&quot;type&quot;
      :disabled=&quot;disabled&quot;
    &gt;</code></pre>
<pre><code class="js">    type: {
      type: String,
      default: &#39;text&#39;
    },</code></pre>
<h3 id="禁用按钮-disabled"><a href="#禁用按钮-disabled" class="headerlink" title="禁用按钮-disabled"></a>禁用按钮-disabled</h3><p>结构</p>
<pre><code class="html">&lt;div class=&quot;sy-input&quot;&gt;
  &lt;input
         class=&quot;sy-input__inner&quot;
         :class=&quot;{&#39;is-disabled&#39;: disabled}&quot;
         :placeholder=&quot;placeholder&quot;
         :type=&quot;type&quot;
         :disabled=&quot;disabled&quot;
         &gt;
&lt;/div&gt;</code></pre>
<p>js</p>
<pre><code class="js">    disabled: {
      type: Boolean,
      default: false
    }</code></pre>
<p>样式</p>
<pre><code class="html">    &amp;.is-disabled {
      background-color: #f5f7fa;
      border-color: #e4e7ed;
      color: #c0c4cc;
      cursor: not-allowed;
    }</code></pre>
<h3 id="v-model语法糖"><a href="#v-model语法糖" class="headerlink" title="v-model语法糖"></a>v-model语法糖</h3><ul>
<li>v-model语法糖</li>
</ul>
<pre><code class="js">给普通表单元素元素使用v-model
&lt;input type=&quot;text&quot; v-model=&quot;mes&quot;&gt;
&lt;input v-bind:value=&quot;mes&quot;  v-on:input=&quot;mes= $event.target.value&quot;/&gt;

给组件使用v-model指令,实质上相当于给组件传递了value属性以及监听了input事件
&lt;sy-input v-model=&quot;msg&quot;&gt;
等价与
&lt;sy-input v-bind:value=&quot;mes&quot;  v-on:input=&quot;mes= arguments[0]&quot;/&gt;</code></pre>
<ul>
<li>html结构</li>
</ul>
<pre><code class="html">&lt;div class=&quot;sy-input&quot;&gt;
  &lt;input
         class=&quot;sy-input__inner&quot;
         :class=&quot;{&#39;is-disabled&#39;: disabled}&quot;
         :placeholder=&quot;placeholder&quot;
         :type=&quot;type&quot;
         :disabled=&quot;disabled&quot;
         :value=&quot;value&quot;
         @input=&quot;handleInput&quot;
         &gt;
&lt;/div&gt;</code></pre>
<p>js</p>
<pre><code class="js">
props: {
  value: [String, Number]
},
methods: {
    handleInput (e) {
      this.$emit(&#39;input&#39;, e.target.value)
    }
  }</code></pre>
<h3 id="clearable与show-password处理"><a href="#clearable与show-password处理" class="headerlink" title="clearable与show-password处理"></a>clearable与show-password处理</h3><p>如果给input组件传入clearable属性，会显示一个清空的按钮，如果传入show-password，则会显示一个用于切换密码显示的处理</p>
<ul>
<li>基本结构</li>
</ul>
<pre><code class="html">&lt;span class=&quot;sy-input__suffix&quot;&gt;
  &lt;i class=&quot;sy-input__icon sy-icon-circle-close&quot;&gt;&lt;/i&gt;
  &lt;i class=&quot;sy-input__icon sy-icon-view&quot;&gt;&lt;/i&gt;
&lt;/span&gt;</code></pre>
<ul>
<li>props接收</li>
</ul>
<pre><code class="js">clearable: {
  type: Boolean,
  default: false
},
showPassword: {
  type: Boolean,
  default: false
}</code></pre>
<ul>
<li>控制按钮显示和隐藏</li>
</ul>
<pre><code class="html">&lt;span class=&quot;sy-input__suffix&quot;&gt;
  &lt;i class=&quot;sy-input__icon sy-icon-circle-close&quot; v-if=&quot;clearable&quot;&gt;&lt;/i&gt;
  &lt;i class=&quot;sy-input__icon sy-icon-view&quot; v-if=&quot;showPassword&quot;&gt;&lt;/i&gt;
&lt;/span&gt;</code></pre>
<p>样式</p>
<pre><code class="scss">.sy-input--suffix {
  .sy-input__inner {
    padding-right: 30px;
  }
  .sy-input__suffix {
    position: absolute;
    height: 100%;
    right: 10px;
    top: 0;
    line-height: 40px;
    text-align: center;
    color: #c0c4cc;
    transition: all .3s;
    z-index: 900;
    i {
      color: #c0c4cc;
      font-size: 14px;
      cursor: pointer;
      transition: color .2s cubic-bezier(.645,.045,.355,1);
    }
  }
}</code></pre>
<ul>
<li>控制<code>sy-input--suffix</code>的类名</li>
</ul>
<pre><code class="html">&lt;div class=&quot;sy-input&quot; :class=&quot;{&#39;sy-input--suffix&#39;: this.clearable || this.showPassword}&quot;&gt;

&lt;span class=&quot;sy-input__suffix&quot; v-if=&quot;this.clearable || this.showPassword&quot;&gt;</code></pre>
<ul>
<li>使用计算属性优化</li>
</ul>
<pre><code class="js">computed: {
  showSuffix () {
    return this.clearable || this.showPassword
  }
}</code></pre>
<ul>
<li>注册事件-清空内容和切换密码显示</li>
</ul>
<pre><code class="js">    clear () {
      // console.log(&#39;123&#39;)
      this.$emit(&#39;input&#39;, &#39;&#39;)
    }</code></pre>
<ul>
<li>控制密码显示</li>
</ul>
<pre><code class="js">data () {
  return {
    // 是否显示密码
    passwordVisible: false
  }
},

&lt;input
  class=&quot;sy-input__inner&quot;
  :class=&quot;{&#39;is-disabled&#39;: disabled}&quot;
  :placeholder=&quot;placeholder&quot;
  :type=&quot;showPassword ? (passwordVisible ? &#39;text&#39;: &#39;password&#39;) : type&quot;
  :name=&quot;name&quot;
  :disabled=&quot;disabled&quot;
  :value=&quot;value&quot;
  @input=&quot;handleInput&quot;
  ref=&quot;input&quot;
&gt;

handlePasswordVisible () {
  // 切换type类型
  this.passwordVisible = !this.passwordVisible
}</code></pre>
<h3 id="其他常见事件的支持"><a href="#其他常见事件的支持" class="headerlink" title="其他常见事件的支持"></a>其他常见事件的支持</h3><pre><code class="js">    handleFocus (e) {
      this.$emit(&#39;focus&#39;, e)
    },
    handleBlur (e) {
      this.$emit(&#39;blur&#39;, e)
    },
    handleChange (e) {
      this.$emit(&#39;change&#39;, e.target.value)
    }</code></pre>
<h2 id="switch组件"><a href="#switch组件" class="headerlink" title="switch组件"></a>switch组件</h2><h3 id="参数支持-3"><a href="#参数支持-3" class="headerlink" title="参数支持"></a>参数支持</h3><table>
<thead>
<tr>
<th>参数名称</th>
<th>参数描述</th>
<th>参数类型</th>
<th>默认值</th>
</tr>
</thead>
<tbody><tr>
<td>v-model</td>
<td>双向绑定</td>
<td>布尔类型</td>
<td>false</td>
</tr>
<tr>
<td>name</td>
<td>name属性</td>
<td>string</td>
<td>text</td>
</tr>
<tr>
<td>activeColor</td>
<td>自定义的激活的颜色</td>
<td>string</td>
<td></td>
</tr>
<tr>
<td>inactiveColor</td>
<td>自定义的不激活的颜色</td>
<td>string</td>
<td></td>
</tr>
</tbody></table>
<h3 id="事件支持-3"><a href="#事件支持-3" class="headerlink" title="事件支持"></a>事件支持</h3><table>
<thead>
<tr>
<th>事件名称</th>
<th>事件描述</th>
</tr>
</thead>
<tbody><tr>
<td>change</td>
<td>change时触发的事件</td>
</tr>
</tbody></table>
<h3 id="基本结构-3"><a href="#基本结构-3" class="headerlink" title="基本结构"></a>基本结构</h3><ul>
<li>页面</li>
</ul>
<pre><code class="html">&lt;template&gt;
  &lt;label class=&quot;sy-switch&quot;&gt;
    &lt;span class=&quot;sy-switch__core&quot;&gt;
      &lt;span class=&quot;sy-switch__button&quot;&gt;&lt;/span&gt;
    &lt;/span&gt;
  &lt;/label&gt;
&lt;/template&gt;</code></pre>
<ul>
<li>样式</li>
</ul>
<pre><code class="scss">.sy-switch {
  display: inline-flex;
  align-items: center;
  position: relative;
  font-size: 14px;
  line-height: 20px;
  height: 20px;
  vertical-align: middle;
  .sy-switch__core {
    margin: 0;
    display: inline-block;
    position: relative;
    width: 40px;
    height: 20px;
    border: 1px solid #dcdfe6;
    outline: none;
    border-radius: 10px;
    box-sizing: border-box;
    background: #dcdfe6;
    cursor: pointer;
    transition: border-color .3s,background-color .3s;
    vertical-align: middle;
    .sy-switch__button {
      position: absolute;
      top: 1px;
      left: 1px;
      border-radius: 100%;
      transition: all .3s;
      width: 16px;
      height: 16px;
      background-color: #fff;
    }
  }
}</code></pre>
<h3 id="v-mode双向绑定"><a href="#v-mode双向绑定" class="headerlink" title="v-mode双向绑定"></a>v-mode双向绑定</h3><ul>
<li>接收value值</li>
</ul>
<pre><code class="js">props: {
  value: {
    type: Boolean,
    default: false
  }
},</code></pre>
<ul>
<li>注册点击事件</li>
</ul>
<pre><code class="html">&lt;div class=&quot;sy-switch&quot; @click=&quot;handleClick&quot;&gt;</code></pre>
<ul>
<li>事件处理程序</li>
</ul>
<pre><code class="js">methods: {
  handleClick () {
    this.$emit(&#39;input&#39;, !this.value)
  }
}</code></pre>
<ul>
<li>选中样式</li>
</ul>
<pre><code class="scss">.sy-switch.is-checked {
  .sy-switch__core {
    border-color: #409eff;
    background-color: #409eff;
    .sy-switch__button {
      transform: translateX(20px);
    }
  }
}</code></pre>
<ul>
<li>控制选中样式</li>
</ul>
<pre><code class="html">&lt;div class=&quot;sy-switch&quot; @click=&quot;handleClick&quot; :class=&quot;{&#39;is-checked&#39;: value}&quot;&gt;</code></pre>
<h3 id="自定义颜色"><a href="#自定义颜色" class="headerlink" title="自定义颜色"></a>自定义颜色</h3><p>在使用switch时，希望能够自定义开关的颜色</p>
<pre><code class="html">&lt;sy-switch
  v-model=&quot;value&quot;
  active-color=&quot;#13ce66&quot;
  inactive-color=&quot;#ff4949&quot;&gt;
&lt;/sy-switch&gt;</code></pre>
<ul>
<li>props接收</li>
</ul>
<pre><code class="js">activeColor: {
  type: String,
  default: &#39;&#39;
},
inactiveColor: {
  type: String,
  default: &#39;&#39;
}</code></pre>
<ul>
<li>封装设置颜色的方法</li>
</ul>
<pre><code class="js">setColor () {
  if (this.activeColor || this.inactiveColor) {
    let color = this.value ? this.activeColor : this.inactiveColor
    this.$refs.core.style.borderColor = color
    this.$refs.core.style.backgroundColor = color
  }
}</code></pre>
<ul>
<li>页面一进入调用</li>
</ul>
<pre><code class="js">mounted () {
  // 设置颜色
  this.setColor()
},</code></pre>
<ul>
<li>改变状态后调用</li>
</ul>
<pre><code class="js">async handleClick () {
  this.$emit(&#39;input&#39;, !this.value)
  // 改变input框的值
  await this.$nextTick()
  this.setColor()
},</code></pre>
<h3 id="name属性支持"><a href="#name属性支持" class="headerlink" title="name属性支持"></a>name属性支持</h3><p>用户在使用switch组件的时候，实质上是当成表单元素来使用的。因此可能会用到组件的name属性。<strong>因此需要在switch组件中添加一个checkbox，并且当值改变的时候，也需要设置checkbox的value值</strong></p>
<ul>
<li>结构</li>
</ul>
<pre><code class="html">&lt;input
  class=&quot;sy-switch__input&quot;
  type=&quot;checkbox&quot;
&gt;</code></pre>
<ul>
<li>样式</li>
</ul>
<pre><code class="scss">.sy-switch__input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  margin: 0;
}</code></pre>
<ul>
<li>name属性的支持</li>
</ul>
<pre><code class="js">name: {
  type: String,
  default: &#39;&#39;
}</code></pre>
<ul>
<li>控制checkbox的值与value同步</li>
</ul>
<pre><code class="js">  mounted () {
    this.$refs.input.checked = this.value
  },
  methods: {
    async handleChange () {
      this.$emit(&#39;input&#39;, !this.value)
      // 修改checkbox的值
      await this.$nextTick()
      this.$refs.input.checked = this.value
    }
  }</code></pre>
<h2 id="radio组件"><a href="#radio组件" class="headerlink" title="radio组件"></a>radio组件</h2><h3 id="前置知识点"><a href="#前置知识点" class="headerlink" title="前置知识点"></a>前置知识点</h3><pre><code class="js">radio的基本使用</code></pre>
<h3 id="参数支持-4"><a href="#参数支持-4" class="headerlink" title="参数支持"></a>参数支持</h3><table>
<thead>
<tr>
<th>参数名称</th>
<th>参数描述</th>
<th>参数类型</th>
<th>默认值</th>
</tr>
</thead>
<tbody><tr>
<td>v-model</td>
<td>双向绑定</td>
<td>布尔类型</td>
<td>false</td>
</tr>
<tr>
<td>label</td>
<td>单选框的value值</td>
<td>string，num,boolean</td>
<td>‘’</td>
</tr>
<tr>
<td>name</td>
<td>name属性</td>
<td>string</td>
<td></td>
</tr>
</tbody></table>
<h3 id="基本结构-4"><a href="#基本结构-4" class="headerlink" title="基本结构"></a>基本结构</h3><ul>
<li>html结构</li>
</ul>
<pre><code class="html">&lt;template&gt;
  &lt;label class=&quot;sy-radio&quot;&gt;
    &lt;span class=&quot;sy-radio__input&quot;&gt;
      &lt;span class=&quot;sy-radio__inner&quot;&gt;&lt;/span&gt;
      &lt;input
        class=&quot;sy-radio__original&quot;
        type=&quot;radio&quot;
      &gt;
    &lt;/span&gt;
    &lt;span class=&quot;sy-radio__label&quot;&gt;
      我是label
    &lt;/span&gt;
  &lt;/label&gt;
&lt;/template&gt;</code></pre>
<ul>
<li>样式</li>
</ul>
<pre><code class="scss">.sy-radio {
  color: #606266;
  font-weight: 500;
  line-height: 1;
  position: relative;
  cursor: pointer;
  display: inline-block;
  white-space: nowrap;
  outline: none;
  font-size: 14px;
  margin-right: 30px;
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  .sy-radio__input {
    white-space: nowrap;
    cursor: pointer;
    outline: none;
    display: inline-block;
    line-height: 1;
    position: relative;
    vertical-align: middle;
    .sy-radio__inner {
      border: 1px solid #dcdfe6;
      border-radius: 100%;
      width: 14px;
      height: 14px;
      background-color: #fff;
      position: relative;
      cursor: pointer;
      display: inline-block;
      box-sizing: border-box;
      &amp;:after {
        width: 4px;
        height: 4px;
        border-radius: 100%;
        background-color: #fff;
        content: &quot;&quot;;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%,-50%) scale(0);
        transition: transform .15s ease-in;
      }
    }
    .sy-radio__original {
      opacity: 0;
      outline: none;
      position: absolute;
      z-index: -1;
      top: 0;
      left: 0px;
      right: 0;
      bottom: 0;
      margin: 0;
    }
  }
  .sy-radio__label {
    font-size: 14px;
    padding-left: 10px;
  }
}</code></pre>
<h3 id="选中的样式"><a href="#选中的样式" class="headerlink" title="选中的样式"></a>选中的样式</h3><pre><code class="js">.sy-radio.is-checked {
  .sy-radio__input {
    .sy-radio__inner {
      border-color: #409eff;
      background: #409eff;
      &amp;:after {
        transform: translate(-50%,-50%) scale(1);
      }
    }
  }
  .sy-radio__label {
    color: #409eff;
  }
}</code></pre>
<h3 id="label与插槽的处理"><a href="#label与插槽的处理" class="headerlink" title="label与插槽的处理"></a>label与插槽的处理</h3><ul>
<li>props接收</li>
</ul>
<pre><code class="js">props: {
  label: {
    type: String,
    default: &#39;&#39;
  },
  name: {
    type: String,
    default: &#39;&#39;
  }
}</code></pre>
<ul>
<li>处理插槽</li>
</ul>
<pre><code class="html">&lt;span class=&quot;sy-radio__label&quot;&gt;
  &lt;slot&gt;&lt;/slot&gt;
  &lt;!-- 如果没有插槽内容，那么label就是内容 --&gt;
  &lt;template v-if=&quot;!$slots.default&quot;&gt;{{label}}&lt;/template&gt;
&lt;/span&gt;</code></pre>
<h3 id="v-model处理"><a href="#v-model处理" class="headerlink" title="v-model处理"></a>v-model处理</h3><ul>
<li>接收props数据</li>
</ul>
<pre><code class="js">name: {
  type: String,
  default: &#39;&#39;
},
value: {
  type: [String, Boolean, Number],
  default: &#39;&#39;
}</code></pre>
<ul>
<li>结构</li>
</ul>
<pre><code class="html">&lt;input
  class=&quot;sy-radio__original&quot;
  type=&quot;radio&quot;
  :name=&quot;name&quot;
  value=&quot;label&quot;
  v-model=&quot;model&quot;
&gt;</code></pre>
<ul>
<li>提供计算属性</li>
</ul>
<pre><code class="html">computed: {
  model: {
    get () {
      return this.value
    },
    set (value) {
      this.$emit(&#39;input&#39;, value)
    }
  }
},
</code></pre>
<ul>
<li>控制选中样式</li>
</ul>
<pre><code class="html">&lt;label class=&quot;sy-radio&quot; :class=&quot;{&#39;is-checked&#39;: model === label}&quot;&gt;
</code></pre>
<h2 id="radio-group组件"><a href="#radio-group组件" class="headerlink" title="radio-group组件"></a>radio-group组件</h2><p>使用radio组件的缺点，需要给每个组件都绑定v-mode,可以使用radio-group包裹</p>
<h3 id="前置知识-2"><a href="#前置知识-2" class="headerlink" title="前置知识"></a>前置知识</h3><pre><code class="js">provide与inject
</code></pre>
<h3 id="基本结构-5"><a href="#基本结构-5" class="headerlink" title="基本结构"></a>基本结构</h3><p>结构</p>
<pre><code class="html">&lt;template&gt;
  &lt;div class=&quot;radio-group&quot;&gt;
    &lt;slot&gt;&lt;/slot&gt;
  &lt;/div&gt;
&lt;/template&gt;
</code></pre>
<p>数据</p>
<pre><code class="html">export default {
  name: &#39;HmRadioGroup&#39;,
  provide () {
    return {
      RadioGroup: this
    }
  },
  props: {
    value: null
  }
}
</code></pre>
<h3 id="修改radio组件"><a href="#修改radio组件" class="headerlink" title="修改radio组件"></a>修改radio组件</h3><ul>
<li>接收inject</li>
</ul>
<pre><code class="js">inject: {
  RadioGroup: {
    default: &#39;&#39;
  }
},
</code></pre>
<ul>
<li>计算属性判断是否包裹在group中</li>
</ul>
<pre><code class="js">// 判断包裹在group中
isGroup () {
  return !!this.RadioGroup
}
</code></pre>
<ul>
<li>修改代码</li>
</ul>
<pre><code class="js">model: {
  get () {
    return this.isGroup ? this.RadioGroup.value : this.value
  },
  set (value) {
    this.isGroup ? this.RadioGroup.$emit(&#39;input&#39;, value) : this.$emit(&#39;input&#39;, value)
  }
}
</code></pre>
<h2 id="checkbox组件"><a href="#checkbox组件" class="headerlink" title="checkbox组件"></a>checkbox组件</h2><h3 id="基本结构-6"><a href="#基本结构-6" class="headerlink" title="基本结构"></a>基本结构</h3><pre><code class="html">&lt;template&gt;
  &lt;label class=&quot;sy-checkbox&quot;&gt;
    &lt;span class=&quot;sy-checkbox__input&quot;&gt;
      &lt;span class=&quot;sy-checkbox__inner&quot;&gt;&lt;/span&gt;
      &lt;input type=&quot;checkbox&quot; class=&quot;sy-checkbox__original&quot;&gt;
    &lt;/span&gt;
    &lt;span class=&quot;sy-checkbox__label&quot;&gt;
      &lt;slot&gt;&lt;/slot&gt;
      &lt;template v-if=&quot;!$slots.default&quot;&gt;{{label}}&lt;/template&gt;
    &lt;/span&gt;
  &lt;/label&gt;
&lt;/template&gt;
</code></pre>
<p>样式</p>
<pre><code class="scss">.sy-checkbox {
  color: #606266;
  font-weight: 500;
  font-size: 14px;
  position: relative;
  cursor: pointer;
  display: inline-block;
  white-space: nowrap;
  user-select: none;
  margin-right: 30px;
  .sy-checkbox__input {
    white-space: nowrap;
    cursor: pointer;
    outline: none;
    display: inline-block;
    line-height: 1;
    position: relative;
    vertical-align: middle;
    .sy-checkbox__inner {
      display: inline-block;
      position: relative;
      border: 1px solid #dcdfe6;
      border-radius: 2px;
      box-sizing: border-box;
      width: 14px;
      height: 14px;
      background-color: #fff;
      z-index: 1;
      transition: border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);
      &amp;:after {
        box-sizing: content-box;
        content: &quot;&quot;;
        border: 1px solid #fff;
        border-left: 0;
        border-top: 0;
        height: 7px;
        left: 4px;
        position: absolute;
        top: 1px;
        transform: rotate(45deg) scaleY(0);
        width: 3px;
        transition: transform .15s ease-in .05s;
        transform-origin: center;
      }
    }
    .sy-checkbox__original {
      opacity: 0;
      outline: none;
      position: absolute;
      left: 10px;
      margin: 0;
      width: 0;
      height: 0;
      z-index: -1;
    }
  }
  .sy-checkbox__label {
    display: inline-block;
    padding-left: 10px;
    line-height: 19px;
    font-size: 14px;
  }
}
</code></pre>
<h3 id="选中的样式-1"><a href="#选中的样式-1" class="headerlink" title="选中的样式"></a>选中的样式</h3><pre><code class="scss">.sy-checkbox.is-checked {
  .sy-checkbox__input {
    .sy-checkbox__inner {
      background-color: #409eff;
      border-color: #409eff;
      &amp;:after {
        transform: rotate(45deg) scaleY(1);
      }
    }
  }
  .sy-checkbox__label {
    color: #409eff;
  }
}
</code></pre>
<h3 id="接收props数据"><a href="#接收props数据" class="headerlink" title="接收props数据"></a>接收props数据</h3><pre><code class="js">value: {
  type: Boolean,
  default: false
},
name: {
  type: String,
  default: &#39;&#39;
},
label: {
  type: String,
  default: &#39;&#39;
}
</code></pre>
<h3 id="控制checked样式"><a href="#控制checked样式" class="headerlink" title="控制checked样式"></a>控制checked样式</h3><ul>
<li>控制label</li>
</ul>
<pre><code class="html">&lt;span class=&quot;sy-checkbox__label&quot;&gt;
  &lt;slot&gt;&lt;/slot&gt;
  &lt;template v-if=&quot;!$slots.default&quot;&gt;{{label}}&lt;/template&gt;
&lt;/span&gt;
</code></pre>
<ul>
<li>提供model计算属性</li>
</ul>
<pre><code class="js">model: {
  get () {
    return this.value
  },
  set (value) {
    this.$emit(&#39;input&#39;, value)
  }
}
</code></pre>
<ul>
<li>判断是否选中</li>
</ul>
<pre><code class="js">&lt;label class=&quot;sy-checkbox&quot; :class=&quot;{&#39;is-checked&#39;: value}&quot;&gt;
</code></pre>
<h2 id="checkbox-group组件"><a href="#checkbox-group组件" class="headerlink" title="checkbox-group组件"></a>checkbox-group组件</h2><p>使用checkbox-group组件包裹checkbox</p>
<h3 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h3><pre><code class="html">&lt;template&gt;
  &lt;div class=&quot;sy-checkbox-group&quot;&gt;
    &lt;slot&gt;&lt;/slot&gt;
  &lt;/div&gt;
&lt;/template&gt;

</code></pre>
<ul>
<li>提供provide</li>
</ul>
<pre><code class="js">props: {
  value: {
    type: Array,
    default: function () {
      return []
    }
  }
},
provide () {
  return {
    CheckboxGroup: this
  }
}
</code></pre>
<h3 id="修改checkbox"><a href="#修改checkbox" class="headerlink" title="修改checkbox"></a>修改checkbox</h3><ul>
<li>接收inject</li>
</ul>
<pre><code class="js">inject: {
  CheckboxGroup: {
    default: &#39;&#39;
  }
},
</code></pre>
<ul>
<li>修改</li>
</ul>
<pre><code class="js">    model: {
      get () {
        return this.isGroup ? this.CheckboxGroup.value : this.value
      },
      set (value) {
        if (this.isGroup) {
          // 修改value属性
          console.log(value, this.label)
          this.CheckboxGroup.$emit(&#39;input&#39;, value)
        } else {
          this.$emit(&#39;input&#39;, value)
        }
      }
    },  
isGroup () {
    return !!this.CheckboxGroup
  },
  isChecked () {
    // 判断是否选中
    // console.log(this.model)
    if (this.isGroup) {
      return this.model.includes(this.label)
    } else {
      return this.model
    }
  }
</code></pre>
<h2 id="form组件"><a href="#form组件" class="headerlink" title="form组件"></a>form组件</h2><p>基本结构</p>
<pre><code class="html">&lt;template&gt;
  &lt;div class=&quot;sy-form&quot;&gt;
    &lt;slot&gt;&lt;/slot&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  name: &#39;HmForm&#39;,
  provide () {
    return {
      Form: this
    }
  },
  props: {
    model: {
      type: Object,
      required: true
    },
    labelWidth: {
      type: String,
      default: &#39;80px&#39;
    }
  }
}
&lt;/script&gt;

&lt;style&gt;

&lt;/style&gt;
</code></pre>
<h2 id="form-item组件"><a href="#form-item组件" class="headerlink" title="form-item组件"></a>form-item组件</h2><p>基本结构</p>
<pre><code class="html">&lt;template&gt;
  &lt;div class=&quot;sy-form-item&quot;&gt;
    &lt;label class=&quot;sy-form-item__label&quot; :style=&quot;labelStyle&quot;&gt;{{label}}&lt;/label&gt;
    &lt;div class=&quot;sy-form-item__content&quot;&gt;
      &lt;slot&gt;&lt;/slot&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  name: &#39;HmFormItem&#39;,
  props: {
    label: {
      type: String,
      default: &#39;&#39;
    }
  },
  inject: [&#39;Form&#39;],
  computed: {
    labelStyle () {
      return {
        width: this.Form.labelWidth
      }
    }
  }
}
&lt;/script&gt;

&lt;style lang=&quot;scss&quot;&gt;
.sy-form-item {
  margin-bottom: 25px;
  .sy-form-item__label {
    text-align: right;
    vertical-align: middle;
    float: left;
    font-size: 14px;
    color: #606266;
    line-height: 40px;
    padding: 0 12px 0 0;
    box-sizing: border-box;
  }
  .sy-form-item__content {
    line-height: 40px;
    position: relative;
    font-size: 14px;
    overflow: hidden;
  }
}
&lt;/style&gt;

</code></pre>
<h1 id="封装成UI组件库"><a href="#封装成UI组件库" class="headerlink" title="封装成UI组件库"></a>封装成UI组件库</h1><h2 id="目录调整"><a href="#目录调整" class="headerlink" title="目录调整"></a>目录调整</h2><ul>
<li>根目录创建两个文件夹<code>packages</code>和<code>examples</code></li>
</ul>
<pre><code class="js">packages: 用于存放所有的组件
examples: 用于进行测试,把src改成examples
</code></pre>
<ul>
<li><p>把components中所有的组件放入到packages中</p>
</li>
<li><p>把fonts放到packages中</p>
</li>
<li><p>删除原来的src目录</p>
</li>
</ul>
<h2 id="vue-config-js配置"><a href="#vue-config-js配置" class="headerlink" title="vue.config.js配置"></a>vue.config.js配置</h2><p>新增<code>vue.config.js</code>配置</p>
<pre><code class="js">const path = require(&#39;path&#39;)
module.exports = {
  pages: {
    index: {
      entry: &#39;examples/main.js&#39;,
      template: &#39;public/index.html&#39;,
      filename: &#39;index.html&#39;
    }
  },
  // 扩展 webpack 配置，使 packages 加入编译
  chainWebpack: config =&gt; {
    config.module
      .rule(&#39;js&#39;)
      .include.add(path.resolve(__dirname, &#39;packages&#39;)).end()
      .use(&#39;babel&#39;)
      .loader(&#39;babel-loader&#39;)
      .tap(options =&gt; {
        // 修改它的选项...
        return options
      })
  }
}
</code></pre>
<ul>
<li>统一导出packages中所有的组件</li>
</ul>
<pre><code class="js">// 统一导出
// 导入颜色选择器组件
import Button from &#39;./button&#39;
import Dialog from &#39;./dialog&#39;
import Input from &#39;./input&#39;
import Checkbox from &#39;./checkbox&#39;
import Radio from &#39;./radio&#39;
import RadioGroup from &#39;./radio-group&#39;
import Switch from &#39;./switch&#39;
import CheckboxGroup from &#39;./checkbox-group&#39;
import Form from &#39;./form&#39;
import FormItem from &#39;./form-item&#39;
import &#39;./fonts/font.scss&#39;

// 存储组件列表
const components = [
  Button,
  Dialog,
  Input,
  Checkbox,
  Radio,
  RadioGroup,
  Switch,
  CheckboxGroup,
  Form,
  FormItem
]

// 定义 install 方法，接收 Vue 作为参数。如果使用 use 注册插件，则所有的组件都将被注册
const install = function (Vue) {
  // 遍历注册全局组件
  components.forEach(component =&gt; {
    Vue.component(component.name, component)
  })
}

// 判断是否是直接引入文件,如果是，就不用调用 Vue.use()
if (typeof window !== &#39;undefined&#39; &amp;&amp; window.Vue) {
  install(window.Vue)
}

// 导出的对象必须具有 install，才能被 Vue.use() 方法安装
export default {
  install
}

</code></pre>
<h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>在examples中的main.js中进行导入测试</p>
<pre><code class="js">import Vue from &#39;vue&#39;
import App from &#39;./App.vue&#39;

import HeimaUI from &#39;../packages&#39;

Vue.use(HeimaUI)

Vue.config.productionTip = false

new Vue({
  render: h =&gt; h(App)
}).$mount(&#39;#app&#39;)

</code></pre>
<h1 id="发布到npm"><a href="#发布到npm" class="headerlink" title="发布到npm"></a>发布到npm</h1><h2 id="发布到npm-1"><a href="#发布到npm-1" class="headerlink" title="发布到npm"></a>发布到npm</h2><p> <a href="https://cli.vuejs.org/zh/guide/build-targets.html#库" target="_blank" rel="noopener">https://cli.vuejs.org/zh/guide/build-targets.html#%E5%BA%93</a> </p>
<ul>
<li>在scripts中新增一条 打包命令</li>
</ul>
<pre><code class="js">&quot;lib&quot;: &quot;vue-cli-service build --target lib packages/index.js&quot;
</code></pre>
<ul>
<li>发布到npm</li>
</ul>
<p>修改package.json文件</p>
<pre><code class="js">&quot;private&quot;: false,
&quot;main&quot;: &quot;dist/songyong-ui.umd.min.js&quot;,
&quot;author&quot;: {
  &quot;name&quot;: &quot;谢芃&quot;
}</code></pre>
<p>增加 <code>.npmignore</code>文件</p>
<pre><code class="js"># 忽略目录
examples/
packages/
public/

# 忽略指定文件
vue.config.js
babel.config.js
*.map
</code></pre>
<ul>
<li>npm发布</li>
</ul>
<pre><code class="js">npm login // 需要先注册账号
npm publish
</code></pre>

            </div>
            <hr>
            <div>
              <p>
                
                
              </p>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a href="https://zh.wikipedia.org/wiki/Wikipedia:CC_BY-SA_3.0%E5%8D%8F%E8%AE%AE%E6%96%87%E6%9C%AC" target="_blank" rel="nofollow noopener noopener">CC BY-SA 3.0协议</a> 。转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <div class="post-prev col-6">
                    
                    
                      <a href="/myblog/2020/07/01/%E7%AE%97%E6%B3%95%E4%B8%8E%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%AC%94%E8%AE%B0/">
                        <i class="fa fa-chevron-left"></i>
                        <span class="hidden-mobile">算法与数据结构笔记</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </div>
                  <div class="post-next col-6">
                    
                    
                      <a href="/myblog/2020/01/04/%E5%9B%BE%E8%A7%A3HTTP%E7%AC%94%E8%AE%B0/">
                        <span class="hidden-mobile">图解HTTP学习笔记</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="fa fa-chevron-right"></i>
                      </a>
                    
                  </div>
                </div>
              
            </div>

              
          </div>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc-start"></div>
<div id="toc">
  <p class="h5"><i class="far fa-list-alt"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a class="z-depth-1" id="scroll-top-button" href="#" role="button">
      <i class="fa fa-chevron-up scroll-top-arrow" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  

  <footer class="mt-5">
  <div class="text-center py-3">
    <div>
      <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><b>Hexo</b></a>
      <i class="iconfont icon-love"></i>
      <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"> <b>Fluid</b></a>
    </div>
    

    

    
  </div>
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/popper.js/1.16.1/umd/popper.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="https://cdn.staticfile.org/mdbootstrap/4.13.0/js/mdb.min.js" ></script>
<script  src="/myblog/js/main.js" ></script>


  <script  src="/myblog/js/lazyload.js" ></script>



  
  <script  src="https://cdn.staticfile.org/tocbot/4.10.0/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var navHeight = $('#navbar').height();
      var toc = $('#toc');
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;
      var tocLimMax = 2 * boardTop + boardCtn.height();

      $(window).scroll(function () {
        var tocLimMin = $('#toc-start').offset().top - navHeight;
        var scroH = document.body.scrollTop + document.documentElement.scrollTop;

        if (tocLimMin <= scroH && scroH <= tocLimMax) {
          toc.css({
            'display': 'block',
            'position': 'fixed',
            'top': navHeight,
          });
        } else if (scroH <= tocLimMin) {
          toc.css({
            'position': '',
            'top': '',
          });
        } else if (scroH > tocLimMax) {
          toc.css('display', 'none');
        }
      });
      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '.post-content',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc > p').css('visibility', 'visible');
      }
      var offset = boardCtn.css('margin-right')
      $('#toc-ctn').css({
        'right': offset
      })
    });
  </script>





  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/myblog/js/clipboard-use.js" ></script>








<!-- Plugins -->



  <script  src="https://cdn.staticfile.org/prettify/188.0.0/prettify.min.js" ></script>
  <script>
    $(document).ready(function () {
      $('pre').addClass('prettyprint  linenums');
      prettyPrint();
    })
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "ui组件封装笔记&nbsp;",
      ],
      cursorChar: "_",
      typeSpeed: 70,
      loop: false,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/myblog/js/local-search.js" ></script>
  <script>
    var path = "/myblog/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      getSearchFile(path);
      this.onclick = null
    }
  </script>



  <script defer src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <script>
    $("#post img:not(.no-zoom img, img[no-zoom])").each(
      function () {
        var element = document.createElement("a");
        $(element).attr("data-fancybox", "images");
        $(element).attr("href", $(this).attr("src"));
        $(this).wrap(element);
      }
    );
  </script>












</body>
</html>
